package com.zzyl.common.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.regex.Pattern;

public class IDCardUtils {
    /**
     * 中国公民身份证号码最小长度。
     */
    public static final int CHINA_ID_MIN_LENGTH = 15;

    /**
     * 中国公民身份证号码最大长度。
     */
    public static final int CHINA_ID_MAX_LENGTH = 18;

    /**
     * 省、直辖市代码表
     */
    public static final String[] CITY_CODE = {
        "11", "12", "13", "14", "15", "21", "22", "23", "31", "32", "33", "34", "35", "36", "37", "41",
        "42", "43", "44", "45", "46", "50", "51", "52", "53", "54", "61", "62", "63", "64", "65", "71", "81", "82", "91"
    };

    /**
     * 每位加权因子
     */
    public static final int[] POWER = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};

    /**
     * 第18位校检码
     */
    public static final String[] VERIFY_CODE = {"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"};

    /**
     * 身份证格式正则表达式
     */
    private static final Pattern ID_CARD_PATTERN = Pattern.compile(
        "^[1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[0-9Xx]$");

    /**
     * 验证身份证是否合法
     */
    public static boolean validateIdCard(String idCard) {
        if (idCard == null || idCard.trim().isEmpty()) {
            return false;
        }

        // 去掉字符串首尾空格
        idCard = idCard.trim();
        
        // 长度验证
        int length = idCard.length();
        if (length != CHINA_ID_MIN_LENGTH && length != CHINA_ID_MAX_LENGTH) {
            return false;
        }

        // 15位身份证号码验证
        if (length == CHINA_ID_MIN_LENGTH) {
            return validate15IdCard(idCard);
        }

        // 18位身份证号码验证
        return validate18IdCard(idCard);
    }

    /**
     * 验证15位身份证
     */
    private static boolean validate15IdCard(String idCard) {
        // 15位身份证没有字母
        if (!idCard.matches("^\\d{15}$")) {
            return false;
        }

        // 省份验证
        String provinceId = idCard.substring(0, 2);
        if (!checkProvinceId(provinceId)) {
            return false;
        }

        // 生日验证
        String birthday = "19" + idCard.substring(6, 12);
        try {
            Date birthDate = new SimpleDateFormat("yyyyMMdd").parse(birthday);
            if (!birthDate.before(new Date())) {
                return false;
            }
        } catch (ParseException e) {
            return false;
        }

        return true;
    }

    /**
     * 验证18位身份证
     */
    private static boolean validate18IdCard(String idCard) {
        // 格式验证
        if (!ID_CARD_PATTERN.matcher(idCard).matches()) {
            return false;
        }

        // 省份验证
        String provinceId = idCard.substring(0, 2);
        if (!checkProvinceId(provinceId)) {
            return false;
        }

        // 生日验证
        String birthday = idCard.substring(6, 14);
        try {
            Date birthDate = new SimpleDateFormat("yyyyMMdd").parse(birthday);
            if (!birthDate.before(new Date())) {
                return false;
            }
        } catch (ParseException e) {
            return false;
        }

        // 第18位验证
        String verifyCode = idCard.substring(17, 18);
        String expectedVerifyCode = getVerifyCode(idCard.substring(0, 17));
        return verifyCode.equalsIgnoreCase(expectedVerifyCode);
    }

    /**
     * 检查省份代码是否合法
     */
    private static boolean checkProvinceId(String provinceId) {
        for (String code : CITY_CODE) {
            if (code.equals(provinceId)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取身份证的第18位校验码
     */
    private static String getVerifyCode(String idCard17) {
        int[] idCardArray = convertIdCard17ToIntArray(idCard17);
        int sum = 0;
        for (int i = 0; i < 17; i++) {
            sum += idCardArray[i] * POWER[i];
        }
        int mod = sum % 11;
        return VERIFY_CODE[mod];
    }

    /**
     * 将身份证前17位转换为int数组
     */
    private static int[] convertIdCard17ToIntArray(String idCard17) {
        int[] arr = new int[17];
        for (int i = 0; i < 17; i++) {
            arr[i] = Integer.parseInt(String.valueOf(idCard17.charAt(i)));
        }
        return arr;
    }

    /**
     * 从身份证号码中获取出生日期字符串，格式：yyyy-MM-dd
     */
    public static String getBirthdayStr(String idCard) {
        if (!validateIdCard(idCard)) {
            return null;
        }
        
        String birthday;
        if (idCard.length() == CHINA_ID_MIN_LENGTH) {
            // 15位身份证转为18位处理
            birthday = "19" + idCard.substring(6, 12);
        } else {
            birthday = idCard.substring(6, 14);
        }
        
        try {
            Date birthDate = new SimpleDateFormat("yyyyMMdd").parse(birthday);
            return new SimpleDateFormat("yyyy-MM-dd").format(birthDate);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 从身份证号码中获取出生日期
     */
    public static Date getBirthday(String idCard) {
        String birthdayStr = getBirthdayStr(idCard);
        if (birthdayStr == null) {
            return null;
        }
        
        try {
            return new SimpleDateFormat("yyyy-MM-dd").parse(birthdayStr);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 根据身份证号码计算年龄
     */
    public static int getAgeFromIDCard(String idCard) {
        Date birthDate = getBirthday(idCard);
        if (birthDate == null) {
            return 0;
        }
        
        Calendar birth = Calendar.getInstance();
        birth.setTime(birthDate);
        
        Calendar now = Calendar.getInstance();
        
        // 计算年龄
        int age = now.get(Calendar.YEAR) - birth.get(Calendar.YEAR);
        
        // 如果当前日期在生日之前，则年龄减一
        if (now.get(Calendar.DAY_OF_YEAR) < birth.get(Calendar.DAY_OF_YEAR)) {
            age--;
        }
        
        return Math.max(age, 0);
    }

    /**
     * 根据出生日期计算年龄
     */
    public static int getAge(Date birthday) {
        if (birthday == null) {
            return 0;
        }
        
        Calendar birth = Calendar.getInstance();
        birth.setTime(birthday);
        
        Calendar now = Calendar.getInstance();
        
        // 计算年龄
        int age = now.get(Calendar.YEAR) - birth.get(Calendar.YEAR);
        
        // 如果当前日期在生日之前，则年龄减一
        if (now.get(Calendar.DAY_OF_YEAR) < birth.get(Calendar.DAY_OF_YEAR)) {
            age--;
        }
        
        return Math.max(age, 0);
    }

    /**
     * 从身份证号码中获取性别
     * @return 1:男，2:女，0:未知
     */
    public static int getGender(String idCard) {
        if (!validateIdCard(idCard)) {
            return 0;
        }
        
        String genderCode;
        if (idCard.length() == CHINA_ID_MIN_LENGTH) {
            genderCode = idCard.substring(14, 15);
        } else {
            genderCode = idCard.substring(16, 17);
        }
        
        int genderNum = Integer.parseInt(genderCode);
        return genderNum % 2 == 0 ? 2 : 1;
    }

    /**
     * 从身份证号码中获取省份
     */
    public static String getProvince(String idCard) {
        if (!validateIdCard(idCard)) {
            return null;
        }
        
        String provinceId = idCard.substring(0, 2);
        for (String code : CITY_CODE) {
            if (code.equals(provinceId)) {
                return getProvinceNameByCode(code);
            }
        }
        return null;
    }

    /**
     * 根据省份代码获取省份名称
     */
    private static String getProvinceNameByCode(String code) {
        // 实际应用中可以使用Map存储省份代码和名称的映射关系
        switch (code) {
            case "11": return "北京";
            case "12": return "天津";
            case "13": return "河北";
            case "14": return "山西";
            case "15": return "内蒙古";
            case "21": return "辽宁";
            case "22": return "吉林";
            case "23": return "黑龙江";
            case "31": return "上海";
            case "32": return "江苏";
            case "33": return "浙江";
            case "34": return "安徽";
            case "35": return "福建";
            case "36": return "江西";
            case "37": return "山东";
            case "41": return "河南";
            case "42": return "湖北";
            case "43": return "湖南";
            case "44": return "广东";
            case "45": return "广西";
            case "46": return "海南";
            case "50": return "重庆";
            case "51": return "四川";
            case "52": return "贵州";
            case "53": return "云南";
            case "54": return "西藏";
            case "61": return "陕西";
            case "62": return "甘肃";
            case "63": return "青海";
            case "64": return "宁夏";
            case "65": return "新疆";
            case "71": return "台湾";
            case "81": return "香港";
            case "82": return "澳门";
            case "91": return "国外";
            default: return null;
        }
    }
}    